package com.sinochem.yunlian.ship.common.util;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.UUID;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class SSOAuthUtils
{
    private static final String IV_STRING = "16-Bytes--String";
    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
    private static final String MD5 = "MD5";
    private static final String AES = "AES";
    private static final String AES_PADDING = "AES/CBC/PKCS5Padding";
    private static final String SHA_1 = "SHA-1";
    private static final String SHA_256 = "SHA-256";
    private static Mac mac;
    private static SecretKeySpec signingKey;
    private static Cipher cipher;
    private static MessageDigest md;
    private static Base64.Encoder encoder;

    public static String getAuthorization(String token, String method, String uri, long timestamp, String nonce, String devKey, String devSecret)
            throws NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException
    {
        StringBuilder signStr = new StringBuilder().append(token).append(method).append(uri).append(timestamp).append(devSecret).append(nonce).append(devKey);

        String signature = getSignature(signStr.toString(), devSecret);

        return md5(signature);
    }

    public static String getAuthorizationWithoutToken(String method, String uri, long timestamp, String nonce, String devKey, String devSecret)
            throws NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException
    {
        StringBuilder signStr = new StringBuilder().append(method).append(uri).append(timestamp).append(devSecret).append(nonce).append(devKey);

        String signature = getSignature(signStr.toString(), devSecret);

        return md5(signature);
    }

    public static String generateNonce(int len)
    {
        String key = UUID.randomUUID().toString();
        key = key.replace("-", "").substring(0, len);

        return key;
    }

    private static String base64Encode(byte[] b)
    {
        if (encoder == null) {
            encoder = Base64.getEncoder();
        }
        return encoder.encodeToString(b);
    }

    private static String getSignature(String data, String secret)
            throws NoSuchAlgorithmException, InvalidKeyException
    {
        if (null == mac)
        {
            SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), "HmacSHA1");
            mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
        }
        byte[] rawHmac = mac.doFinal(data.getBytes());

        return base64Encode(rawHmac);
    }

    private static String md5(String source)
            throws NoSuchAlgorithmException
    {
        if (md == null) {
            md = MessageDigest.getInstance("MD5");
        }
        byte[] result = md.digest(source.getBytes());
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < result.length; i++)
        {
            byte b = result[i];
            buf.append(String.format("%02X", new Object[] { Byte.valueOf(b) }));
        }
        return buf.toString().toLowerCase();
    }
}
